package com.ruoyi.order.service.impl;

import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.conversation.domain.Conversation;
import com.ruoyi.conversation.mapper.ConversationMapper;
import com.ruoyi.dddetails.domain.DdDetails;
import com.ruoyi.dddetails.mapper.DdDetailsMapper;
import com.ruoyi.descriptionrule.domain.DescriptionRule;
import com.ruoyi.descriptionrule.service.IDescriptionRuleService;
import com.ruoyi.disease.domain.Disease;
import com.ruoyi.disease.mapper.DiseaseMapper;
import com.ruoyi.distributionrule.domain.DistributionRule;
import com.ruoyi.distributionrule.mapper.DistributionRuleMapper;
import com.ruoyi.doctordisease.domain.DoctorDisease;
import com.ruoyi.doctordisease.mapper.DoctorDiseaseMapper;
import com.ruoyi.doctorlibrary.domain.DoctorLibrary;
import com.ruoyi.doctorlibrary.domain.vo.DoctorLibraryVO;
import com.ruoyi.doctorlibrary.mapper.DoctorLibraryMapper;
import com.ruoyi.evaluate.domain.Evaluate;
import com.ruoyi.evaluate.mapper.EvaluateMapper;
import com.ruoyi.finance.domain.Finance;
import com.ruoyi.finance.mapper.FinanceMapper;
import com.ruoyi.income.domain.Income;
import com.ruoyi.income.mapper.IncomeMapper;
import com.ruoyi.order.domain.OrderIgnored;
import com.ruoyi.order.domain.event.OrderMessageEvent;
import com.ruoyi.order.domain.request.*;
import com.ruoyi.order.domain.vo.*;
import com.ruoyi.order.mapper.OrderIgnoredMapper;
import com.ruoyi.orderdoctor.domain.OrderDoctor;
import com.ruoyi.orderdoctor.mapper.OrderDoctorMapper;
import com.ruoyi.ordersubscriberefundrecord.domain.OrderSubscribeRefundRecord;
import com.ruoyi.ordersubscriberefundrecord.mapper.OrderSubscribeRefundRecordMapper;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.userdisease.domain.UserDisease;
import com.ruoyi.userdisease.mapper.UserDiseaseMapper;
import com.ruoyi.wx.utils.GetUserUtils;
import com.ruoyi.wx.utils.WeChatTokenManager;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.http.*;
import com.wechat.pay.java.core.http.Constant;
import com.wechat.pay.java.core.notification.*;
import com.wechat.pay.java.core.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import com.ruoyi.order.mapper.OrderMapper;
import com.ruoyi.order.domain.Order;
import com.ruoyi.order.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.service.partnerpayments.app.model.PrepayResponse;

import javax.servlet.http.HttpServletRequest;

import static com.ruoyi.wx.utils.WeChatTokenManager.*;
import static com.ruoyi.wx.utils.WeChatTokenManager.getProgramUserAccessToken;

/**
 * 【订单】Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-03
 */
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDoctorMapper orderDoctorMapper;

    @Autowired
    private DoctorLibraryMapper doctorLibraryMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EvaluateMapper evaluateMapper;

    @Autowired
    private UserDiseaseMapper userDiseaseMapper;

    @Autowired
    private DiseaseMapper diseaseMapper;

    @Autowired
    private OrderIgnoredMapper orderIgnoredMapper;

    @Autowired
    private IDescriptionRuleService descriptionRuleService;

    @Autowired
    private ApplicationEventPublisher publisher;

    @Autowired
    private DoctorDiseaseMapper doctorDiseaseMapper;

    @Autowired
    private OrderSubscribeRefundRecordMapper orderSubscribeRefundRecordMapper;

    @Autowired
    private DdDetailsMapper ddDetailsMapper;

    @Autowired
    private DistributionRuleMapper distributionRuleMapper;

    @Autowired
    private IncomeMapper incomeMapper;

    @Autowired
    private FinanceMapper financeMapper;
    @Autowired
    private ConversationMapper conversationMapper;

    /**
     * 查询【请填写功能名称】
     *
     * @param orderId 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public OrderVO selectOrderByOrderId(String orderId) {
        Order order = orderMapper.selectOrderByOrderId(orderId);
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        // 根据订单id查询订单对应的医生
        OrderDoctor orderDoctor = new OrderDoctor();
        orderDoctor.setOrderId(order.getOrderId());
        List<OrderDoctor> orderDoctors = orderDoctorMapper.selectOrderDoctorList(orderDoctor);
        ArrayList<DoctorLibrary> doctorLibraries = new ArrayList<>();
        for (OrderDoctor doctor : orderDoctors) {
            DoctorLibrary doctorLibrary = doctorLibraryMapper.selectDoctorLibraryByDoctorId(doctor.getDoctorId());
            doctorLibraries.add(doctorLibrary);
        }
        orderVO.setDoctorLibraryList(doctorLibraries);
        // 根据用户id查询用户
        User user = userMapper.selectUserByUserId(order.getUserId());
        // 根据专家名查询专家
        User expert = userMapper.selectUserByUserId(order.getExpertId());
        Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order.getDiseaseId());
        orderVO.setIllness(disease.getIllnessName());
        orderVO.setUser(user);
        orderVO.setExpert(expert);
        return orderVO;
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param order 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<Order> selectOrderList(Order order) {
        // 查询订单列表
        List<Order> orders = orderMapper.selectOrderList(order);
        return orders;
    }

    @Override
    public List<OrderVO> selectAllOrderList(List<Order> orders) {
        ArrayList<OrderVO> orderVOS = new ArrayList<>();
        for (Order order1 : orders) {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order1, orderVO);
            // 根据订单id查询订单对应的医生
            OrderDoctor orderDoctor = new OrderDoctor();
            orderDoctor.setOrderId(order1.getOrderId());
            List<OrderDoctor> orderDoctors = orderDoctorMapper.selectOrderDoctorList(orderDoctor);
            ArrayList<DoctorLibrary> doctorLibraries = new ArrayList<>();
            for (OrderDoctor doctor : orderDoctors) {
                DoctorLibrary doctorLibrary = doctorLibraryMapper.selectDoctorLibraryByDoctorId(doctor.getDoctorId());
                doctorLibraries.add(doctorLibrary);
            }
            orderVO.setDoctorLibraryList(doctorLibraries);
            // 根据用户id查询用户
            User user = userMapper.selectUserByUserId(order1.getUserId());
            // 根据专家名查询专家
            User expert = userMapper.selectUserByUserId(order1.getExpertId());
            Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order1.getDiseaseId());
            orderVO.setIllness(disease.getIllnessName());
            orderVO.setUser(user);
            orderVO.setExpert(expert);
            orderVOS.add(orderVO);
        }
        return orderVOS;
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param order 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertOrder(Order order) {
        return orderMapper.insertOrder(order);
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param order 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateOrder(Order order) {
        return orderMapper.updateOrder(order);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param orderIds 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderIds(String[] orderIds) {
        return orderMapper.deleteOrderByOrderIds(orderIds);
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param orderId 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderId(String orderId) {
        return orderMapper.deleteOrderByOrderId(orderId);
    }

    /**
     * 根据用户id查询订单列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<OrderVO> selectOrderListByUserId(String userId, String orderStatus, String isEvaluate) {
        // 查询订单列表
        Order order = new Order();
        order.setUserId(userId);
        order.setOrderStatus(orderStatus);
        order.setIsEvaluate(isEvaluate);
        List<Order> orders = orderMapper.selectOrderList(order);
        ArrayList<OrderVO> orderVOS = new ArrayList<>();
        for (Order order1 : orders) {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order1, orderVO);
            // 根据订单id查询订单对应的医生
            OrderDoctor orderDoctor = new OrderDoctor();
            orderDoctor.setOrderId(order1.getOrderId());
            Evaluate evaluate = evaluateMapper.selectEvaluateByOrderId(order1.getOrderId());
            orderVO.setEvaluate(evaluate);
            List<OrderDoctor> orderDoctors = orderDoctorMapper.selectOrderDoctorList(orderDoctor);
            ArrayList<DoctorLibrary> doctorLibraries = new ArrayList<>();
            for (OrderDoctor doctor : orderDoctors) {
                DoctorLibrary doctorLibrary = doctorLibraryMapper.selectDoctorLibraryByDoctorId(doctor.getDoctorId());
                doctorLibraries.add(doctorLibrary);
            }
            Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order1.getDiseaseId());
            orderVO.setDisease(disease);
            orderVO.setDoctorLibraryList(doctorLibraries);
            // 根据用户id查询用户
            User user = userMapper.selectUserByUserId(order1.getUserId());
            // 根据专家名查询专家
            User expert = userMapper.selectUserByUserId(order1.getExpertId());
            orderVO.setUser(user);
            orderVO.setExpert(expert);
            Conversation conversation = new Conversation();
            conversation.setIsOffline(0);
            conversation.setFromRole("expert");
            conversation.setOrderId(order1.getOrderId());
            List<Conversation> conversations = conversationMapper.selectConversationList(conversation);
            if (conversations != null && !conversations.isEmpty()) {
                orderVO.setIsOffline(0);
            } else {
                orderVO.setIsOffline(1);
            }
            orderVOS.add(orderVO);
        }
        return orderVOS;
    }

    /**
     * 根据专家查询可接订单
     *
     * @param seachOrderVO
     * @return
     */
    @Override
    public TableDataInfo findOrderListByDisease(HttpServletRequest request, SeachOrderVO seachOrderVO) {
        String token = request.getHeader("Authorization");
        TableDataInfo tableDataInfo = new TableDataInfo();
        List<OrderVO> orderVOS = new ArrayList<>();
        int orderSize = 0;

        // 登录用户存在并且是 Bearer Token
        if (StringUtils.isNotEmpty(token) && token.startsWith("Bearer ")) {
            User loginUser = GetUserUtils.getLoginUser(request);
            seachOrderVO.setUserId(loginUser.getUserId());
            User user = userMapper.selectUserByUserId(seachOrderVO.getUserId());

            // 非专家用户逻辑
            if (user.getIsExpert() == 0) {
                // 获取用户绑定的病种
                UserDisease query = new UserDisease();
                query.setUserId(user.getUserId());
                List<UserDisease> userDiseases = userDiseaseMapper.selectUserDiseaseList(query);

                if (!userDiseases.isEmpty()) {
                    // 所有用户关联病种ID
                    List<Long> userDiseaseIds = userDiseases.stream()
                            .map(UserDisease::getDiseaseId)
                            .collect(Collectors.toList());

                    List<Long> targetDiseaseIds;

                    if (StringUtils.isBlank(seachOrderVO.getIllnessName())) {
                        // 未搜索病种时，使用全部关联病种
                        targetDiseaseIds = userDiseaseIds;
                    } else {
                        // 模糊匹配搜索病种
                        String illness = "%" + seachOrderVO.getIllnessName() + "%";
                        List<Disease> matchDiseases = diseaseMapper.selectDiseaseByLikeIllness(illness);

                        Set<Long> matchIds = matchDiseases.stream()
                                .map(Disease::getDiseaseId)
                                .collect(Collectors.toSet());

                        // 与用户绑定的病种取交集
                        targetDiseaseIds = userDiseaseIds.stream()
                                .filter(matchIds::contains)
                                .collect(Collectors.toList());
                    }

                    // 查询忽略的订单
                    List<OrderIgnored> orderIgnoreds = orderIgnoredMapper.selectOrderIgnoredByUserId(user.getUserId());
                    List<String> ignoredOrderIds = new ArrayList<>();
                    if (orderIgnoreds != null && !orderIgnoreds.isEmpty()) {
                        ignoredOrderIds = orderIgnoreds.stream()
                                .map(OrderIgnored::getOrderId)
                                .collect(Collectors.toList());
                    }

                    // 构建查询参数
                    OrderQueryDTO orderQueryDTO = new OrderQueryDTO();
                    String[] cityKeywords = user.getAddress().split(",");
                    orderQueryDTO.setCitys(Arrays.asList(cityKeywords));
                    orderQueryDTO.setDiseaseIds(targetDiseaseIds);
                    orderQueryDTO.setOrderIds(ignoredOrderIds);

                    // 查询总条数
                    List<Integer> totalList = orderMapper.selectOrderListByAddressAndDisease1(orderQueryDTO);
                    orderSize = totalList.size();

                    // 分页并查询订单
                    PageHelper.startPage(seachOrderVO.getPageNum(), seachOrderVO.getPageSize());
                    List<Order> orders = orderMapper.selectOrderListByAddressAndDisease(orderQueryDTO);

                    for (Order order : orders) {
                        OrderVO orderVO = new OrderVO();
                        BeanUtils.copyProperties(order, orderVO);
                        Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order.getDiseaseId());
                        orderVO.setDisease(disease);
                        orderVOS.add(orderVO);
                    }
                } else {
                    // 用户没有绑定任何病种，查全部订单（备用逻辑）
                    orderSize = orderMapper.selectOrderList(new Order()).size();
                    PageHelper.startPage(seachOrderVO.getPageNum(), seachOrderVO.getPageSize());
                    List<Order> orders = orderMapper.selectOrderList(new Order());
                    for (Order order : orders) {
                        OrderVO orderVO = new OrderVO();
                        BeanUtils.copyProperties(order, orderVO);
                        Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order.getDiseaseId());
                        orderVO.setDisease(disease);
                        orderVOS.add(orderVO);
                    }
                }
            }
        } else {
            // 未登录用户，查全部订单
            Order orderQuery = new Order();
            orderSize = orderMapper.selectOrderList(orderQuery).size();
            PageHelper.startPage(seachOrderVO.getPageNum(), seachOrderVO.getPageSize());
            List<Order> orders = orderMapper.selectOrderList(orderQuery);
            for (Order order : orders) {
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(order, orderVO);
                Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order.getDiseaseId());
                orderVO.setDisease(disease);
                orderVOS.add(orderVO);
            }
        }

        tableDataInfo.setRows(orderVOS);
        tableDataInfo.setTotal(orderSize);
        return tableDataInfo;
    }


    /**
     * 创建订单
     *
     * @param order
     * @return
     */
    @Override
    @Transactional
    public String createOrder(Order order) {
        // 当前时间 yyyyMMddHHmmss
        String dateTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        // 当前时间戳的后 4 位
        String timestamp = String.valueOf(System.currentTimeMillis());
        String lastFour = timestamp.substring(timestamp.length() - 4);
        String orderId = dateTime + lastFour;
        order.setOrderId(orderId);
        // 设置下单时间
        order.setPlaceOrderTime(new Date());
        // 设置实付金额
        if (order.getDeduction() != null) {
            User user = userMapper.selectUserByUserId(order.getUserId());
            BigDecimal ddTotalNumber = user.getDdTotalNumber();
            DdDetails ddDetails = new DdDetails();
            // 抵扣大于等于金额
            if (order.getDeduction().compareTo(order.getTotleAmount()) >= 0) {
                BigDecimal subtract = order.getDeduction().subtract(order.getTotleAmount());
                order.setActualPayment(BigDecimal.ZERO);
                order.setDeduction(order.getTotleAmount());
                user.setDdTotalNumber(subtract);
                // 设置订单状态
                order.setOrderStatus("1");
                pushMessageExpert(order);
            } else {
                BigDecimal totleAmount = order.getTotleAmount();
                BigDecimal deduction = order.getDeduction();
                BigDecimal subtract = totleAmount.subtract(deduction);
                order.setActualPayment(subtract);
                // 修改用户叮豆
                user.setDdTotalNumber(ddTotalNumber.subtract(order.getDeduction()));
                // 设置订单状态
                order.setOrderStatus("6");
            }
            userMapper.updateUser(user);
            ddDetails.setId(order.getUserId());
            ddDetails.setSource("订单抵扣");
            ddDetails.setDetails("-" + order.getDeduction());
            ddDetails.setCreateTime(DateUtils.getNowDate());
            ddDetailsMapper.insertDdDetails(ddDetails);
        } else {
            order.setActualPayment(order.getTotleAmount());
            order.setDeduction(BigDecimal.ZERO);
            order.setOrderStatus("6");
        }
        // 设置会话
        order.setIsSession(0);
        order.setIsEvaluate("1");
        BigDecimal deduction = order.getDeduction();
        if (deduction == null) {
            order.setDeduction(BigDecimal.ZERO);
        }
        orderMapper.insertOrder(order);
        return orderId;
    }


    /**
     * 支付
     *
     * @param orderId
     * @return
     */
    @Transactional
    @Override
    public WeChatPayVo orderPay(String orderId) {
        Order order = orderMapper.selectOrderByOrderId(orderId);
        if ("0".equals(order.getPayStatus())) {
            return null;
        } else {
            User user = userMapper.selectUserByUserId(order.getUserId());
            WeChatPayRequest weChatPayRequest = new WeChatPayRequest();
            weChatPayRequest.setOutTradeNo(orderId);
            BigDecimal actualPayment = order.getActualPayment();
            // 支付金额 分
            BigDecimal payMoney = actualPayment.multiply(new BigDecimal(100));
            WeChatPayRequest.WeChatPayAmountRequest amountRequest = new WeChatPayRequest.WeChatPayAmountRequest();
            amountRequest.setTotal(payMoney.intValue());
            weChatPayRequest.setAmount(amountRequest);
            weChatPayRequest.setDescription("咨询");
            //支付人信息
            WeChatPayRequest.WeChatPayPayerRequest payPayerRequest = new WeChatPayRequest.WeChatPayPayerRequest();
            payPayerRequest.setOpenId(user.getOpenId());
            weChatPayRequest.setPayer(payPayerRequest);
            // 实付
            order.setActualPayment(actualPayment);
            WeChatPayVo weChatPayVo = weChatAppletPay(weChatPayRequest);
            String timeStamp = weChatPayVo.getTimeStamp();
            order.setPayTime(new Date(Long.parseLong(timeStamp) * 1000));
            return weChatPayVo;
        }
    }

    /**
     * 忽略订单
     *
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public AjaxResult isIgnoreOrder(String userId, String orderId) {
        OrderIgnored orderIgnored = new OrderIgnored();
        orderIgnored.setUserId(userId);
        orderIgnored.setOrderId(orderId);
        int i = orderIgnoredMapper.insertOrderIgnored(orderIgnored);
        return AjaxResult.success("忽略成功");
    }

    /**
     * 查询专家订单列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<OrderVO> selectOrderListByExpertId(String userId, String orderStatus, String isEvaluate) {
        // 查询订单列表
        Order order = new Order();
        order.setExpertId(userId);
        order.setOrderStatus(orderStatus);
        order.setIsEvaluate(isEvaluate);
        List<Order> orders = orderMapper.selectOrderList(order);
        ArrayList<OrderVO> orderVOS = new ArrayList<>();
        for (Order order1 : orders) {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order1, orderVO);
            // 根据订单id查询订单对应的医生
            OrderDoctor orderDoctor = new OrderDoctor();
            orderDoctor.setOrderId(order1.getOrderId());
            Evaluate evaluate = evaluateMapper.selectEvaluateByOrderId(order1.getOrderId());
            orderVO.setEvaluate(evaluate);
            List<OrderDoctor> orderDoctors = orderDoctorMapper.selectOrderDoctorList(orderDoctor);
            ArrayList<DoctorLibraryVO> doctorLibraries = new ArrayList<>();
            if (!orderDoctors.isEmpty()) {
                for (OrderDoctor doctor : orderDoctors) {
                    DoctorLibraryVO doctorLibraryVO = new DoctorLibraryVO();
                    DoctorLibrary doctorLibrary = doctorLibraryMapper.selectDoctorLibraryByDoctorId(doctor.getDoctorId());
                    if (doctorLibrary != null) {
                        BeanUtils.copyProperties(doctorLibrary, doctorLibraryVO);
                        DoctorDisease doctorDisease1 = doctorDiseaseMapper.selectDoctorDiseaseByDoctorId(doctor.getDoctorId());
                        Disease disease = diseaseMapper.selectDiseaseByDiseaseId(doctorDisease1.getDiseaseId());
                        doctorLibraryVO.setDisease(disease);
                        doctorLibraries.add(doctorLibraryVO);
                    }
                }
            }
            orderVO.setDoctorLibraryVOList(doctorLibraries);
            Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order1.getDiseaseId());
            orderVO.setDisease(disease);
            // 根据用户id查询用户
            User user = userMapper.selectUserByUserId(order1.getUserId());
            // 根据专家名查询专家
            User expert = userMapper.selectUserByUserId(order1.getExpertId());
            orderVO.setUser(user);
            orderVO.setExpert(expert);
            Conversation conversation = new Conversation();
            conversation.setIsOffline(0);
            conversation.setFromRole("user");
            conversation.setOrderId(order1.getOrderId());
            List<Conversation> conversations = conversationMapper.selectConversationList(conversation);
            if (conversations != null && !conversations.isEmpty()) {
                orderVO.setIsOffline(0);
            } else {
                orderVO.setIsOffline(1);
            }
            orderVOS.add(orderVO);
        }
        return orderVOS;
    }

    /**
     * 查询用户订单
     *
     * @param oderId
     * @return
     */
    @Override
    public OrderVO selectOrderByUserId(String oderId) {
        Order order = orderMapper.selectOrderByOrderId(oderId);
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        // 根据订单id查询订单对应的医生
        OrderDoctor orderDoctor = new OrderDoctor();
        orderDoctor.setOrderId(order.getOrderId());
        List<OrderDoctor> orderDoctors = orderDoctorMapper.selectOrderDoctorList(orderDoctor);
        if (orderDoctors != null && !orderDoctors.isEmpty()) {
            ArrayList<DoctorLibraryVO> doctorLibraries = new ArrayList<>();
            for (OrderDoctor doctor : orderDoctors) {
                DoctorLibraryVO doctorLibraryVO = new DoctorLibraryVO();
                DoctorLibrary doctorLibrary = doctorLibraryMapper.selectDoctorLibraryByDoctorId(doctor.getDoctorId());
                if (doctorLibrary != null) {
                    BeanUtils.copyProperties(doctorLibrary, doctorLibraryVO);
                    DoctorDisease doctorDisease1 = doctorDiseaseMapper.selectDoctorDiseaseByDoctorId(doctor.getDoctorId());
                    Disease disease = diseaseMapper.selectDiseaseByDiseaseId(doctorDisease1.getDiseaseId());
                    doctorLibraryVO.setDisease(disease);
                    doctorLibraries.add(doctorLibraryVO);
                }
            }
            orderVO.setDoctorLibraryVOList(doctorLibraries);
        }
        Disease disease = diseaseMapper.selectDiseaseByDiseaseId(order.getDiseaseId());
        orderVO.setDisease(disease);
        // 根据用户id查询用户
        User user = userMapper.selectUserByUserId(order.getUserId());
        // 根据专家名查询专家
        User expert = userMapper.selectUserByUserId(order.getExpertId());
        orderVO.setUser(user);
        orderVO.setExpert(expert);
        return orderVO;
    }

    /**
     * 专家接单
     *
     * @param userId
     * @param orderId
     * @return
     */
    @Transactional
    @Override
    public String takingOrder(String userId, String orderId) {
        User expert = userMapper.selectUserByUserId(userId);
        if ("0".equals(expert.getUserStatus())) {
            Order order = orderMapper.selectOrderByOrderId(orderId);
            order.setExpertId(userId);
            order.setOrderStatus("2");
            order.setOrderTakingTime(new Date());
            orderMapper.updateOrder(order);
            // 专家
            DistributionRule distributionRule = new DistributionRule();
            DistributionRule distributionRule1 = distributionRuleMapper.selectDistributionRuleList(distributionRule).get(0);
            // 提成百分比
            Integer commission = 100;
            // 专家接单提成  接单提成百分比
            String orderCommission = distributionRule1.getOrderCommission();
            // 转换成 BigDecimal 并除以 100，变成 0.1
            BigDecimal commissionRate = new BigDecimal(orderCommission).divide(BigDecimal.valueOf(100));
            // 推荐专家提成
            String expertCommission = distributionRule1.getExpertCommission();
            BigDecimal expertCommissionRate = new BigDecimal(expertCommission).divide(BigDecimal.valueOf(100));
            // 用户提成
            String userCommission = distributionRule1.getUserCommission();
            BigDecimal userCommissionRate = new BigDecimal(userCommission).divide(BigDecimal.valueOf(100));
            // 订单实付
            BigDecimal actualPayment = order.getActualPayment();
            // 订单抵扣叮豆
            BigDecimal deduction = order.getDeduction();
            if (actualPayment.compareTo(BigDecimal.ZERO) != 0) {
                // 接单提成金额
                BigDecimal commissionAmount = actualPayment.multiply(commissionRate);
                // 接单提成之后的百分百
                commission = commission - Integer.valueOf(orderCommission);
                // 专家累计金额
                BigDecimal totalAmount = expert.getTotalAmount();
                BigDecimal add = totalAmount.add(commissionAmount);
                // 添加收益记录
                Income income = new Income();
                income.setOrderId(order.getOrderId());
                income.setSource("接单收益");
                income.setIncomeDetails("+" + commissionAmount.setScale(2, RoundingMode.HALF_UP));
                income.setUserId(expert.getUserId());
                income.setUsername(order.getOrderId());
                income.setCreateTime(DateUtils.getNowDate());
                if (commissionAmount.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.ZERO) != 0) {
                    incomeMapper.insertIncome(income);
                }
                // 总金额
                expert.setTotalAmount(add);
                expert.setFreezeAmount(expert.getFreezeAmount().add(commissionAmount));
            }
            // 叮豆收益
            BigDecimal ddmultiply = deduction.multiply(commissionRate);
            if (ddmultiply.compareTo(BigDecimal.ZERO) != 0) {
                // 专家叮豆总数
                BigDecimal ddTotalNumber = expert.getDdTotalNumber();
                BigDecimal add1 = ddTotalNumber.add(ddmultiply);
                expert.setDdTotalNumber(add1);
                expert.setCumulativeDd(expert.getCumulativeDd().add(ddTotalNumber));
                // 添加叮豆记录
                DdDetails ddDetails = new DdDetails();
                ddDetails.setId(expert.getUserId());
                ddDetails.setSource("接单收益");
                ddDetails.setDetails("+" + ddmultiply.setScale(2, RoundingMode.HALF_UP));
                ddDetails.setCreateTime(DateUtils.getNowDate());
                if (ddmultiply.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.ZERO) != 0) {
                    ddDetailsMapper.insertDdDetails(ddDetails);
                }
            }
            userMapper.updateUser(expert);
            // 专家的邀请人
            String inviterId = expert.getInviterId();
            if (!"".equals(inviterId) && inviterId != null) {
                // 该专家的推荐人提成 2%
                User user1 = userMapper.selectUserByUserId(inviterId);
                if (user1 != null) {
                    if (actualPayment.compareTo(BigDecimal.ZERO) != 0) {
                        commission = commission - Integer.valueOf(expertCommission);
                        // 推荐人收益
                        BigDecimal expertIncome = actualPayment.multiply(expertCommissionRate);
                        BigDecimal expertRoralNumber = user1.getTotalAmount().add(expertIncome);
                        user1.setTotalAmount(expertRoralNumber);
                        user1.setFreezeAmount(user1.getFreezeAmount().add(expertIncome));
                        Income expertIncome1 = new Income();
                        expertIncome1.setUserId(user1.getUserId());
                        expertIncome1.setSource("分销收益");
                        BigDecimal bigDecimal = expertIncome.setScale(2, RoundingMode.HALF_UP);
                        expertIncome1.setIncomeDetails("+" + bigDecimal);
                        expertIncome1.setUsername(expert.getName());
                        expertIncome1.setOrderId(orderId);
                        expertIncome1.setCreateTime(DateUtils.getNowDate());
                        if (bigDecimal.compareTo(BigDecimal.ZERO) != 0) {
                            incomeMapper.insertIncome(expertIncome1);
                        }
                    }
                    // 推荐人叮豆收益
                    BigDecimal ddDetailsmultiply = deduction.multiply(expertCommissionRate);
                    if (ddDetailsmultiply.compareTo(BigDecimal.ZERO) != 0) {
                        BigDecimal ddTotalNumber1 = user1.getDdTotalNumber().add(ddDetailsmultiply);
                        user1.setDdTotalNumber(ddTotalNumber1);
                        user1.setCumulativeDd(user1.getCumulativeDd().add(ddDetailsmultiply));
                        DdDetails ddDetails1 = new DdDetails();
                        ddDetails1.setId(user1.getUserId());
                        ddDetails1.setSource("分销收益");
                        ddDetails1.setDetails("+" + ddDetailsmultiply.setScale(2, RoundingMode.HALF_UP));
                        ddDetails1.setCreateTime(DateUtils.getNowDate());
                        if (ddDetailsmultiply.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.ZERO) != 0) {
                            ddDetailsMapper.insertDdDetails(ddDetails1);
                        }
                    }
                    userMapper.updateUser(user1);
                }
            }
            // 患者
            User user = userMapper.selectUserByUserId(order.getUserId());
            if (user != null) {
                // 患者邀请人
                String inviterId1 = user.getInviterId();
                if (!"".equals(inviterId1) && inviterId1 != null) {
                    // 该患者的推荐人提成 3%
                    User user1 = userMapper.selectUserByUserId(inviterId1);
                    if (user1 != null) {
                        if (user1.getIsExpert() == 0L) {
                            if (actualPayment.compareTo(BigDecimal.ZERO) != 0) {
                                // 推荐人收益
                                BigDecimal expertIncome = actualPayment.multiply(userCommissionRate);
                                commission = commission - Integer.valueOf(userCommission);
                                BigDecimal expertRoralNumber = user1.getTotalAmount().add(expertIncome);
                                user1.setTotalAmount(expertRoralNumber);
                                user1.setFreezeAmount(user1.getFreezeAmount().add(expertIncome));
                                Income expertIncome1 = new Income();
                                expertIncome1.setUserId(user1.getUserId());
                                expertIncome1.setSource("分销收益");
                                expertIncome1.setIncomeDetails("+" + expertIncome.setScale(2, RoundingMode.HALF_UP));
                                expertIncome1.setOrderId(orderId);
                                expertIncome1.setUsername(user.getName());
                                expertIncome1.setCreateTime(DateUtils.getNowDate());
                                if (expertIncome.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.ZERO) != 0) {
                                    incomeMapper.insertIncome(expertIncome1);
                                }
                            }
                        }
                        // 推荐人叮豆收益
                        BigDecimal ddDetailsmultiply = deduction.multiply(userCommissionRate);
                        if (ddDetailsmultiply.compareTo(BigDecimal.ZERO) != 0) {
                            BigDecimal ddTotalNumber1 = user1.getDdTotalNumber().add(ddDetailsmultiply);
                            user1.setDdTotalNumber(ddTotalNumber1);
                            user1.setCumulativeDd(user1.getCumulativeDd().add(ddDetailsmultiply));
                            DdDetails ddDetails1 = new DdDetails();
                            ddDetails1.setId(user1.getUserId());
                            ddDetails1.setSource("分销收益");
                            ddDetails1.setDetails("+" + ddDetailsmultiply.setScale(2, RoundingMode.HALF_UP));
                            ddDetails1.setCreateTime(DateUtils.getNowDate());
                            if (ddDetailsmultiply.setScale(2, RoundingMode.HALF_UP).compareTo(BigDecimal.ZERO) != 0) {
                                ddDetailsMapper.insertDdDetails(ddDetails1);
                            }
                        }
                        userMapper.updateUser(user1);
                    }
                }
            }
            if (actualPayment.compareTo(BigDecimal.ZERO) != 0) {
                // 平台收益
                Finance finance = new Finance();
                finance.setOrderId(orderId);
                finance.setDiseaseId(order.getDiseaseId());
                finance.setTotalAmount(order.getActualPayment());
                finance.setDdTotalAmount(order.getDeduction());
                finance.setDrawProportion(commission + "%");
                BigDecimal commission1 = new BigDecimal(commission).divide(BigDecimal.valueOf(100));
                BigDecimal multiply = order.getActualPayment().multiply(commission1);
                finance.setDrawAmount(multiply);
                BigDecimal multiply1 = order.getDeduction().multiply(commission1);
                finance.setDrawDdNum(multiply1);
                finance.setCreateTime(DateUtils.getNowDate());
                financeMapper.insertFinance(finance);
            }
            return "接单成功";
        } else {
            return "您的账户已被禁用";
        }
    }

    @Override
    public List<Integer> selectByUserId(String userId, String orderStatus, String isEvaluate) {
        Order order = new Order();
        order.setUserId(userId);
        order.setOrderStatus(orderStatus);
        order.setIsEvaluate(isEvaluate);
        return orderMapper.selectBy(order);
    }

    @Override
    public List<Integer> selectListByExpertId(String userId, String orderStatus, String isEvaluate) {
        Order order = new Order();
        order.setExpertId(userId);
        order.setOrderStatus(orderStatus);
        order.setIsEvaluate(isEvaluate);
        return orderMapper.selectBy(order);
    }

    public WeChatPayVo weChatAppletPay(WeChatPayRequest request) {
        this.initWxPayClient();
        WeChatPayVo vo = new WeChatPayVo();
        request.setAppid("wxd5c95147647b267d");
        request.setMchId("1722646112");
        // 回调
        request.setNotifyUrl("http://123.56.48.228:8080/wx/orderPay/paySuccessCallback");

        // 创建HTTP头信息，设置接收和内容类型为JSON
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
        headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
        headers.addHeader(Constant.WECHAT_PAY_SERIAL, "PUB_KEY_ID_0117226461122025071700291836002400");
        headers.addHeader(Constant.VERSION, "1.1");
        // 构建HTTP请求，设置请求方法为POST，URL为微信支付API接口地址
        HttpRequest httpRequest =
                null;
        try {
            httpRequest = new HttpRequest.Builder()
                    .httpMethod(HttpMethod.POST)
                    .url("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi")
                    .headers(headers)
                    // 设置请求体为createRequestBody方法返回的内容
                    .body(this.createRequestBody(request))
                    .build();
        } catch (JsonProcessingException e) {
            throw new RuntimeException("下单失败");
        }

        // 执行HTTP请求，并将响应体转换为PrepayResponse类对象
        HttpResponse<PrepayResponse> httpResponse = httpClient.execute(httpRequest, PrepayResponse.class);

        // 获取响应体
        ResponseBody responseBody = httpResponse.getBody();

        // 将响应体转换为JSON对象并返回
        String jsonString = JSON.toJSONString(responseBody);
        JSONObject jsonObject = JSONObject.parseObject(jsonString);

        String prepayId = JSONObject.parseObject(jsonObject.getString("body")).getString("prepay_id");
        if (StringUtils.isBlank(prepayId)) {
            throw new RuntimeException("创建微信支付订单失败");
        }
        // 生成签名
        Long timestamp = System.currentTimeMillis() / 1000;

        // 随机字符串
        String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");

        // 生成带签名支付信息
        vo.setAppId("wxd5c95147647b267d");
        vo.setTimeStamp(String.valueOf(timestamp));
        vo.setNonceStr(nonceStr);
        vo.setPackageValue("prepay_id=" + prepayId);
        try {
            String signatureStr = Stream.of("wxd5c95147647b267d", String.valueOf(timestamp), nonceStr, vo.getPackageValue())
                    .collect(Collectors.joining("\n", "", "\n"));
            String sign = this.getSign(signatureStr);
            vo.setPaySign(sign);
            return vo;
        } catch (Exception e) {
            throw new RuntimeException("支付失败");
        }
    }

    public static HttpClient httpClient;

    private void initWxPayClient() {
        // 创建RSAPublicKeyConfig配置对象
        Config config =
                new RSAPublicKeyConfig.Builder()
                        // 设置商户ID
                        .merchantId("1722646112")
                        // 从指定路径加载私钥
                        .privateKey(loadPrivateKeyFromPem("/wxPay/apiclient_key.pem"))
                        // 从指定路径加载公钥
                        .publicKey(loadPublicKeyFromPem("/wxPay/pub_key.pem"))
                        // 设置公钥ID
                        .publicKeyId("PUB_KEY_ID_0117226461122025071700291836002400")
                        // 设置商户API证书的证书序列号
                        .merchantSerialNumber("4874C3B8DC2FE93B88CC7FD007EEAF8F8081895D")
                        // 设置APIv3密钥
                        .apiV3Key("pe2GpfdjrdqcgCZKUXVE6YsdV2cURrCy")
                        // 构建配置对象
                        .build();

        // 创建HttpClient实例，并应用配置
        httpClient =
                new DefaultHttpClientBuilder()
                        // 应用之前创建的配置
                        .config(config)
                        // 设置连接超时时间为500毫秒
                        .connectTimeoutMs(500)
                        // 构建HttpClient实例
                        .build();


    }

    private RequestBody createRequestBody(Object request) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return new JsonRequestBody.Builder().body(mapper.writeValueAsString(request)).build();
    }

    private String getSign(String signatureStr) throws Exception {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromString(loadPrivateKeyFromPem("/wxPay/apiclient_key.pem"));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(merchantPrivateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64Utils.encodeToString(sign.sign());
    }

    private String loadPrivateKeyFromPem(String privateKey) {
        InputStream privateStream = getClass().getResourceAsStream(privateKey);
        if (privateStream == null) {
            throw new RuntimeException("加载私钥失败");
        }
        // 读取私钥文件内容
        StringBuilder keyContentBuilder = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(privateStream, StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                keyContentBuilder.append(line).append("\n");
            }
        } catch (Exception e) {
            throw new RuntimeException("加载私钥失败");
        }

        return keyContentBuilder.toString();

    }

    private String loadPublicKeyFromPem(String publicKey) {
        InputStream privateStream = getClass().getResourceAsStream(publicKey);
        if (privateStream == null) {
            throw new RuntimeException("加载公钥失败");
        }
        // 读取私钥文件内容
        StringBuilder keyContentBuilder = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(privateStream, StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                keyContentBuilder.append(line).append("\n");
            }
        } catch (Exception e) {
            throw new RuntimeException("加载公钥失败");
        }

        return keyContentBuilder.toString();

    }

    /**
     * 支付成功回调
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public HashMap<String, String> paySuccessCallback(HttpServletRequest request) {
        HashMap<String, String> map = new HashMap<>(4);
        try {
            WeChatPayCallbackVo weChatPayCallbackVo = this.weChatAppletPayNotify(request);
            if ("SUCCESS".equals(weChatPayCallbackVo.getFlag())) {
                String transactionId = weChatPayCallbackVo.getTransactionId();
                String outTradeNo = weChatPayCallbackVo.getOutTradeNo();
                OrderVO orderVo = this.selectOrderByOrderId(outTradeNo);
                Order order = new Order();
                BeanUtils.copyProperties(orderVo, order);
                log.info(String.valueOf(order));
                if (order != null) {
                    log.info("订单号:" + outTradeNo + "已支付成功");
                    order.setWxPayId(transactionId);
                    order.setOrderStatus("1");
                    order.setPayTime(new Date());
                    this.updateOrder(order);
                    publisher.publishEvent(new OrderMessageEvent(this, outTradeNo, "订单号:" + outTradeNo + "已支付成功", order.getUserId()));
                    pushMessageExpert(order);
                }
                map.put("code", "200");
                return map;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            map.put("code", "500");
            map.put("FAIL", "失败");
            return map;
        }
        map.put("code", "500");
        map.put("FAIL", "失败");
        log.info(String.valueOf(map));
        return map;
    }

    public WeChatRefundCallbackVo weChatAppletChargebackNotify(HttpServletRequest request) {
        try {
            RequestParam requestParam = buildRequestParam(request);
            WeChatRefundCallbackVo callbackVo = buildNotificationConfig().parse(requestParam, WeChatRefundCallbackVo.class);
            String refundStatus = callbackVo.getRefundStatus();
            // 退款成功
            if ("SUCCESS".equalsIgnoreCase(refundStatus)) {
                callbackVo.setFlag("SUCCESS");
                return callbackVo;
            }
            callbackVo.setFlag("FLAG");
            return callbackVo;
        } catch (Exception e) {
            throw new RuntimeException("微信支付回调失败");
        }
    }


    private RequestParam buildRequestParam(HttpServletRequest request) throws IOException {
        BufferedReader br = request.getReader();
        String str;
        StringBuilder sb = new StringBuilder();
        while ((str = br.readLine()) != null) {
            sb.append(str);
        }
        return new RequestParam.Builder()
                .serialNumber(request.getHeader("Wechatpay-Serial"))
                .nonce(request.getHeader("Wechatpay-Nonce"))
                .signature(request.getHeader("Wechatpay-Signature"))
                .timestamp(request.getHeader("Wechatpay-Timestamp"))
                .body(sb.toString())
                .build();
    }

    private NotificationParser buildNotificationConfig() {
        NotificationConfig config =
                new RSAPublicKeyNotificationConfig.Builder()
//                        .merchantId("1722646112")
//                        .privateKey(loadPrivateKeyFromPem("/wxPay/apiclient_key.pem"))
                        .publicKey(loadPublicKeyFromPem("/wxPay/pub_key.pem"))
                        .publicKeyId("PUB_KEY_ID_0117226461122025071700291836002400")
//                        .merchantSerialNumber("4874C3B8DC2FE93B88CC7FD007EEAF8F8081895D")
                        .apiV3Key("pe2GpfdjrdqcgCZKUXVE6YsdV2cURrCy")
                        .build();
        return new NotificationParser(config);
    }

    public WeChatPayCallbackVo weChatAppletPayNotify(HttpServletRequest request) {
        try {
            RequestParam requestParam = buildRequestParam(request);
            WeChatPayCallbackVo callbackVo = buildNotificationConfig().parse(requestParam, WeChatPayCallbackVo.class);
            String tradeState = callbackVo.getTradeState();
            if ("SUCCESS".equalsIgnoreCase(tradeState)) {
                log.info("订单号:" + callbackVo.getOutTradeNo() + "已支付成功");
                callbackVo.setFlag("SUCCESS");
                return callbackVo;
            }
            log.info("订单号:" + callbackVo.getOutTradeNo() + "已支付失败");
            callbackVo.setFlag("FLAG");
            return callbackVo;

        } catch (IOException e) {
            log.error(e.getMessage());
            throw new RuntimeException("微信支付回调失败");
        }
    }

    /**
     * 订单申请退款
     *
     * @param orderId
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean refundOrder(String orderId) {
        String outRefundNo = System.currentTimeMillis() / 1000 + "";

        OrderVO orderVO = this.selectOrderByOrderId(orderId);
        Order order = new Order();
        BeanUtils.copyProperties(orderVO, order);
        if (order == null) {
            throw new RuntimeException("该订单不存在");
        }
        order.setOutRefundNo(outRefundNo);
        order.setOrderStatus("7");
        order.setIsEvaluate("0");
        if (order.getDeduction() != null && order.getDeduction().compareTo(BigDecimal.ZERO) > 0) {
            User user = userMapper.selectUserByUserId(order.getUserId());
            user.setDdTotalNumber(user.getDdTotalNumber().add(order.getDeduction()));
            order.setOrderStatus("5");
            userMapper.updateUser(user);
            DdDetails ddDetails = new DdDetails();
            ddDetails.setId(user.getUserId());
            ddDetails.setSource("取消订单");
            ddDetails.setDetails("+" + order.getDeduction().setScale(2, RoundingMode.HALF_UP));
            ddDetails.setCreateTime(DateUtils.getNowDate());
            ddDetailsMapper.insertDdDetails(ddDetails);
        }
        if (order.getActualPayment().compareTo(BigDecimal.ZERO) != 0) {
            // 微信退款参数
            WeChatChargeBackRequest request = new WeChatChargeBackRequest();
            request.setOutTradeNo(order.getOrderId());
            request.setTransactionId(order.getWxPayId());
            request.setOutRefundNo(outRefundNo);
            // 退款金额
            WeChatChargeBackRequest.WeChatChargeBackAmountRequest amountRequest = new WeChatChargeBackRequest.WeChatChargeBackAmountRequest();
            amountRequest.setRefund(order.getActualPayment().multiply(new BigDecimal(100)).intValue());
            amountRequest.setTotal(order.getActualPayment().multiply(new BigDecimal(100)).intValue());
            request.setAmount(amountRequest);
            this.weChatAppletChargeback(request);

            publisher.publishEvent(new OrderMessageEvent(this, order.getOrderId(), "订单号:" + order.getOrderId() + "已申请退款", order.getUserId()));
        }
        this.updateOrder(order);
        return true;
    }

    public WeChatChargeBackVo weChatAppletChargeback(WeChatChargeBackRequest request) {
        this.initWxPayClient();
        try {
            request.setNotifyUrl("http://123.56.48.228:8080/wx/orderPay/refundSuccessCallback");

            HttpHeaders headers = new HttpHeaders();
            headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
            headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
            headers.addHeader("Wechatpay-Serial", "PUB_KEY_ID_0117226461122025071700291836002400");

            HttpRequest httpRequest =
                    new HttpRequest.Builder()
                            .httpMethod(HttpMethod.POST)
                            .url("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds")
                            .headers(headers)
                            .body(this.createRequestBody(request))
                            .build();

            HttpResponse<com.wechat.pay.java.service.partnerpayments.nativepay.model.PrepayResponse> httpResponse = httpClient.execute(httpRequest, com.wechat.pay.java.service.partnerpayments.nativepay.model.PrepayResponse.class);

            ResponseBody responseBody = httpResponse.getBody();
            WeChatChargeBackVo chargeBackVo = JSON.parseObject(JSONObject.parseObject(JSON.toJSONString(responseBody)).getString("body"), WeChatChargeBackVo.class);
            if (StringUtils.isBlank(chargeBackVo.getRefundId())) {
                throw new RuntimeException("退单返回数据为空");
            }

            return chargeBackVo;
        } catch (Exception e) {
            throw new RuntimeException("退单返回数据为空");
        }
    }

    /**
     * 退款成功回调
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public HashMap<String, String> refundSuccessCallback(HttpServletRequest request) {
        HashMap<String, String> map = new HashMap<>(4);
        try {
            WeChatRefundCallbackVo weChatRefundCallbackVo = this.weChatAppletChargebackNotify(request);
            if ("SUCCESS".equals(weChatRefundCallbackVo.getFlag())) {
                // 订单号
                String outTradeNo = weChatRefundCallbackVo.getOutTradeNo();
                // 退单单号
                String outRefundNo = weChatRefundCallbackVo.getOutRefundNo();
                // 微信退款单号
                String refundId = weChatRefundCallbackVo.getRefundId();

                OrderVO orderVO = this.selectOrderByOrderId(outTradeNo);
                Order order = new Order();
                BeanUtils.copyProperties(orderVO, order);
                if (order != null) {
                    log.info("订单号:" + outTradeNo + "已退款成功");
                    order.setWeChatRefundOrderNo(refundId);
                    order.setOrderStatus("5");
                    order.setWeChatRefundOrderNo(outRefundNo);
                    order.setRefundTime(new Date());
                    BigDecimal deduction = order.getDeduction();
                    String userId = order.getUserId();
                    User user = userMapper.selectUserByUserId(userId);
                    BigDecimal ddTotalNumber = user.getDdTotalNumber();
                    user.setDdTotalNumber(ddTotalNumber.add(deduction));
                    userMapper.updateUser(user);
                    this.updateOrder(order);

                    // 退款记录
                    OrderSubscribeRefundRecord refundRecord = new OrderSubscribeRefundRecord();
                    refundRecord.setWeChatRefundOrderNo(refundId);
                    refundRecord.setOrderId(order.getOrderId());
//                    refundRecord.setRefundQuantity(order.getActualPayment());
                    refundRecord.setRefundAmount(order.getActualPayment());
                    refundRecord.setOutRefundNo(outRefundNo);
                    orderSubscribeRefundRecordMapper.insertOrderSubscribeRefundRecord(refundRecord);

                    publisher.publishEvent(new OrderMessageEvent(this, outTradeNo, "订单号:" + outTradeNo + "已退款成功", order.getUserId()));

                }
                map.put("code", "200");
                return map;
            }
        } catch (Exception e) {
            map.put("code", "500");
            map.put("FAIL", "失败");
            return map;
        }
        map.put("code", "500");
        map.put("FAIL", "失败");
        return map;
    }

    /**
     * 用户结束会话
     *
     * @param order
     * @return
     */
    @Override
    public AjaxResult endSession(Order order) {
        order.setIsSession(1);
        orderMapper.updateOrder(order);
        return AjaxResult.success("结束会话成功");
    }

    /**
     * 查询专家数据
     *
     * @param loginUser
     * @return
     */
    @Override
    public AjaxResult selectExpertData(User loginUser) {
        DataResult dataResult = new DataResult();
        Order order = new Order();
        order.setExpertId(loginUser.getUserId());
        List<Order> orders = orderMapper.selectOrderList(order);
        dataResult.setTotalOrder(String.valueOf(orders.size()));
        Income income = new Income();
        income.setUserId(loginUser.getUserId());
        List<Income> incomes = incomeMapper.selectIncomeList(income);
        BigDecimal bigDecimal = new BigDecimal(0);
        for (Income income1 : incomes) {
            String incomeDetails = income1.getIncomeDetails();
            if (StringUtils.isNotBlank(incomeDetails) && incomeDetails.length() > 1) {
                incomeDetails = incomeDetails.substring(1);  // 截取第一个字符后面的部分
                bigDecimal = bigDecimal.add(new BigDecimal(incomeDetails));
            }
        }
        dataResult.setTotalAmount(bigDecimal);
        List<Income> incomes1 = incomeMapper.selectTodayIncome(loginUser.getUserId());
        BigDecimal bigDecimal1 = new BigDecimal(0);
        if (incomes1 != null) {
            for (Income income1 : incomes1) {
                String incomeDetails = income1.getIncomeDetails();
                if (StringUtils.isNotBlank(incomeDetails) && incomeDetails.length() > 1) {
                    incomeDetails = incomeDetails.substring(1);  // 截取第一个字符后面的部分
                    bigDecimal1 = bigDecimal1.add(new BigDecimal(incomeDetails));
                }
            }
        }
        dataResult.setTodayAmount(bigDecimal1);
        User user = userMapper.selectUserByUserId(loginUser.getUserId());
        dataResult.setWithdrawAmount(user.getWithdrawableAmount());
        order.setOrderStatus("2");
        List<Order> orders1 = orderMapper.selectOrderList(order);
        dataResult.setDoingOrder(orders1.size());
        order.setOrderStatus("0");
        List<Order> orders2 = orderMapper.selectOrderList(order);
        dataResult.setCompletedOrder(orders2.size());
        // 当前月
        LocalDate now = LocalDate.now();
        // 获取日期区间
        List<String[]> strings = splitMonthBy7Days(now);
        dataResult.setThisMonth(strings);
        List<BigDecimal> thisMonthSales = new ArrayList<>();
        for (String[] string : strings) {
            BigDecimal bigDecimal2 = BigDecimal.ZERO;
            List<Income> incomesDate = incomeMapper.selectDate(string[0], string[1], loginUser.getUserId());
            for (Income income1 : incomesDate) {
                String incomeDetails = income1.getIncomeDetails();
                if (StringUtils.isNotBlank(incomeDetails) && incomeDetails.length() > 1) {
                    incomeDetails = incomeDetails.substring(1);  // 截取第一个字符后面的部分
                    bigDecimal2 = bigDecimal2.add(new BigDecimal(incomeDetails));
                }
            }
            thisMonthSales.add(bigDecimal2);
        }
        dataResult.setThisMonthSales(thisMonthSales);
        // 上个月
        LocalDate lastMonth = now.minusMonths(1);
        // 获取日期区间
        List<String[]> lastMonthDate = splitMonthBy7Days(lastMonth);
        dataResult.setLastMonth(lastMonthDate);
        List<BigDecimal> lastMonthSales = new ArrayList<>();
        for (String[] string : lastMonthDate) {
            BigDecimal bigDecimal2 = BigDecimal.ZERO;
            List<Income> incomesDate = incomeMapper.selectDate(string[0], string[1], loginUser.getUserId());
            for (Income income1 : incomesDate) {
                String incomeDetails = income1.getIncomeDetails();
                if (StringUtils.isNotBlank(incomeDetails) && incomeDetails.length() > 1) {
                    incomeDetails = incomeDetails.substring(1);  // 截取第一个字符后面的部分
                    bigDecimal2 = bigDecimal2.add(new BigDecimal(incomeDetails));
                }
            }
            lastMonthSales.add(bigDecimal2);
        }
        dataResult.setLastMonthSales(lastMonthSales);
        return AjaxResult.success(dataResult);
    }

    /**
     * 推送专家审核信息
     *
     * @return
     */
    @Override
    public AjaxResult pushMessage(String userId, String processStatus) {
        // 获取 access_token
        String accessToken = getExpertAccessToken();
        // 获取用户 openId
        User user = userMapper.selectUserByUserId(userId);
        String openId = user.getServiceOpenId();
//        String openId = "obT6kvi54A1Wl4evcSiXvngHpysw";
        // 构建消息数据
        Map<String, Object> data = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowStr = sdf.format(DateUtils.getNowDate());
//        data.put("time1", createData(nowStr));
        data.put("time2", createData(nowStr));
        data.put("const4", createData(processStatus));

        // 构建完整请求体
        Map<String, Object> payload = new HashMap<>();
        payload.put("touser", openId);
        payload.put("template_id", "gBSM7FsBmlawQs4kBtDwgWq8dKlw86BLHao3FmFOYVY");
//        payload.put("miniprogram_state", "trial");
//        payload.put("lang", "zh_CN");
        Map<String, Object> miniprogram = new HashMap<>();
        miniprogram.put("appid", "wx8348c4fdb4ade875");
//        miniprogram.put("pagepath", "pages/receivingOrders/receivingOrders");
        miniprogram.put("page", "pages/receivingOrders/receivingOrders");
        payload.put("miniprogram", miniprogram);
        payload.put("data", data);

        // 发送请求
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
        String result = HttpUtil.post(url, JSONUtil.toJsonStr(payload));
        return AjaxResult.success(result);
    }


    @Override
    public AjaxResult qrCode(QrCodeVO qrCodeVO) {
        String urlStr = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + qrCodeVO.getAccessToken();

        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/json");

            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("scene", "inviterId=" + qrCodeVO.getInvitationCode());
            requestBody.put("page", "pages/login/login");
            requestBody.put("width", 430);
            requestBody.put("is_hyaline", true);
            requestBody.put("check_path", false);
            requestBody.put("env_version", "release");
//            requestBody.put("env_version", "trial");

            // 写入请求体数据
            try (OutputStream os = connection.getOutputStream();
                 OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8")) {
                osw.write(requestBody.toJSONString());
                osw.flush();
            }

            int responseCode = connection.getResponseCode();
            log.info("响应码: {}", responseCode);
            if (responseCode == 200) {
                try (InputStream inputStream = connection.getInputStream();
                     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        byteArrayOutputStream.write(buffer, 0, bytesRead);
                    }
                    byte[] data = byteArrayOutputStream.toByteArray();

                    // 将二进制数据转换为 Base64 编码
                    String base64 = Base64.getEncoder().encodeToString(data);
                    log.info("二维码数据: {}", base64);
                    return AjaxResult.success(base64);
                }
            } else {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
                    StringBuilder errorResponse = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        errorResponse.append(line);
                    }
                    System.err.println("请求失败，状态码: " + responseCode + ", 错误信息: " + errorResponse);
                    return AjaxResult.error("请求失败: " + responseCode);
                }
            }
        } catch (IOException e) {
            System.err.println("网络错误: " + e.getMessage());
            return AjaxResult.error("网络错误");
        }
    }

    /**
     * 推送接单消息给用户
     *
     * @param orderId
     * @return
     */
    @Override
    public AjaxResult pushMessageUser(String orderId) {

        String accessToken = getProgramUserAccessToken();
        Order order = orderMapper.selectOrderByOrderId(orderId);

        User user = userMapper.selectUserByUserId(order.getUserId());

        String openId = user.getOpenId();
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;

        Map<String, Object> param = new HashMap<>();
        param.put("touser", openId);
        param.put("template_id", "RVA1Mrld0bhVFuLUcn7OpXgIs-IUIXC_QRsw3x6K2qg");
        param.put("page", "pages/order/details?orderId=" + orderId);
        param.put("miniprogram_state", "formal");
        param.put("lang", "zh_CN");

        // 构造消息内容
        Map<String, Object> data = new HashMap<>();

        Map<String, String> character_string1 = new HashMap<>();
        character_string1.put("value", order.getOrderId());
        data.put("character_string1", character_string1);

        Map<String, String> date2 = new HashMap<>();
        String submitTimeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", order.getOrderTakingTime());
        date2.put("value", submitTimeStr);
        data.put("date2", date2);

        param.put("data", data);

        String result = HttpUtil.post(url, JSON.toJSONString(param));
        return AjaxResult.success(result);
    }

    /**
     * 推送新订单信息给专家
     * @param order
     * @return
     */
    @Override
    public AjaxResult pushMessageExpert(Order order) {
        ArrayList<String> results = new ArrayList<>();
        // 获取一次 access_token，避免多次调用
        String accessToken = getExpertAccessToken();
        UserDisease userDisease = new UserDisease();
        userDisease.setDiseaseId(order.getDiseaseId());
        List<UserDisease> userDiseases = userDiseaseMapper.selectUserDiseaseList(userDisease);
        for (UserDisease disease : userDiseases) {
            User user = userMapper.selectUserByUserId(disease.getUserId());
            Disease disease1 = diseaseMapper.selectDiseaseByDiseaseId(disease.getDiseaseId());
            String openId = user.getServiceOpenId();
            String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;

            Map<String, Object> param = new HashMap<>();
            param.put("touser", openId);
            param.put("template_id", "BfIRRYTsL7Fb9Eh0mERmY-FD_nzvvI2YR-kAGKT6cKo");
//            param.put("page", "pages/receivingOrders/receivingOrders?orderId=" + order.getOrderId());
//            param.put("miniprogram_state", "trial");
//            param.put("lang", "zh_CN");
            Map<String, Object> miniprogram = new HashMap<>();
            miniprogram.put("appid", "wx8348c4fdb4ade875");
//            miniprogram.put("pagepath", "pages/order/details?orderId=" + order.getOrderId());
            miniprogram.put("page", "pages/order/details?orderId=" + order.getOrderId());

            param.put("miniprogram", miniprogram);

            // 构造消息内容
            Map<String, Object> data = new HashMap<>();

            Map<String, String> character_string1 = new HashMap<>();
            character_string1.put("value", order.getOrderId());
            data.put("character_string1", character_string1);

            Map<String, String> thing2 = new HashMap<>();
            thing2.put("value", disease1.getIllnessName());
            data.put("thing2", thing2);

            Map<String, String> time9 = new HashMap<>();
            String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", order.getPlaceOrderTime());
            time9.put("value", timeStr);
            data.put("time9", time9);

            param.put("data", data);


            String result = HttpUtil.post(url, JSON.toJSONString(param));
            results.add(result);
        }

        return AjaxResult.success(results);
    }

    // 构建字段数据（统一格式）
    private static Map<String, String> createData(String value) {
        Map<String, String> map = new HashMap<>();
        map.put("value", value);
        map.put("color", "#173177");
        return map;
    }

    public List<String[]> splitMonthBy7Days(LocalDate month) {
        List<String[]> dateRanges = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 月初 & 月末
        LocalDate firstDay = month.withDayOfMonth(1);
        LocalDate lastDay = month.withDayOfMonth(month.lengthOfMonth());

        LocalDate start = firstDay;
        while (start.isBefore(lastDay) || start.equals(lastDay)) {
            LocalDate end = start.plusDays(6); // 7天一个周期
            if (end.isAfter(lastDay)) {
                end = lastDay; // 最后一组不足7天
            }
            // 保存为字符串数组
            dateRanges.add(new String[]{
                    start.format(formatter), // yyyy-MM-dd
                    end.format(formatter)
            });
            start = end.plusDays(1);
        }

        return dateRanges;
    }

}
